// var gl = canvas.getContext( 'webgl', { preserveDrawingBuffer: true } )
//   ,	w = canvas.width = window.innerWidth
//   ,	h = canvas.height = window.innerHeight
//
//   ,	webgl = {}
//   ,	opts = {
//   projectileAlpha: .8,
//   projectileLineWidth: 1.3,
//   fireworkAngleSpan: .5,
//   baseFireworkVel: 3,
//   addedFireworkVel: 3,
//   gravity: .03,
//   lowVelBoundary: -.2,
//   xFriction: .995,
//   baseShardVel: 1,
//   addedShardVel: .2,
//   fireworks: 1000,
//   baseShardsParFirework: 10,
//   addedShardsParFirework: 10,
//   shardFireworkVelMultiplier: .3,
//   initHueMultiplier: 1/360,
//   runHueAdder: .1/360
// }
//
// webgl.vertexShaderSource = `
// uniform int u_mode;
// uniform vec2 u_res;
// attribute vec4 a_data;
// varying vec4 v_color;
//
// vec3 h2rgb( float h ){
// 	return clamp( abs( mod( h * 6. + vec3( 0, 4, 2 ), 6. ) - 3. ) -1., 0., 1. );
// }
// void clear(){
// 	gl_Position = vec4( a_data.xy, 0, 1 );
// 	v_color = vec4( 0, 0, 0, a_data.w );
// }
// void draw(){
// 	gl_Position = vec4( vec2( 1, -1 ) * ( ( a_data.xy / u_res ) * 2. - 1. ), 0, 1 );
// 	v_color = vec4( h2rgb( a_data.z ), a_data.w );
// }
// void main(){
// 	if( u_mode == 0 )
// 		draw();
// 	else
// 		clear();
// }
// `;
// webgl.fragmentShaderSource = `
// precision mediump float;
// varying vec4 v_color;
//
// void main(){
// 	gl_FragColor = v_color;
// }
// `;
//
// webgl.vertexShader = gl.createShader( gl.VERTEX_SHADER );
// gl.shaderSource( webgl.vertexShader, webgl.vertexShaderSource );
// gl.compileShader( webgl.vertexShader );
//
// webgl.fragmentShader = gl.createShader( gl.FRAGMENT_SHADER );
// gl.shaderSource( webgl.fragmentShader, webgl.fragmentShaderSource );
// gl.compileShader( webgl.fragmentShader );
//
// webgl.shaderProgram = gl.createProgram();
// gl.attachShader( webgl.shaderProgram, webgl.vertexShader );
// gl.attachShader( webgl.shaderProgram, webgl.fragmentShader );
//
// gl.linkProgram( webgl.shaderProgram );
// gl.useProgram( webgl.shaderProgram );
//
// webgl.dataAttribLoc = gl.getAttribLocation( webgl.shaderProgram, 'a_data' );
// webgl.dataBuffer = gl.createBuffer();
//
// gl.enableVertexAttribArray( webgl.dataAttribLoc );
// gl.bindBuffer( gl.ARRAY_BUFFER, webgl.dataBuffer );
// gl.vertexAttribPointer( webgl.dataAttribLoc, 4, gl.FLOAT, false, 0, 0 );
//
// webgl.resUniformLoc = gl.getUniformLocation( webgl.shaderProgram, 'u_res' );
// webgl.modeUniformLoc = gl.getUniformLocation( webgl.shaderProgram, 'u_mode' );
//
// gl.viewport( 0, 0, w, h );
// gl.uniform2f( webgl.resUniformLoc, w, h );
//
// gl.blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA );
// gl.enable( gl.BLEND );
//
// gl.lineWidth( opts.projectileLineWidth );
//
// webgl.data = [];
//
// webgl.clear = function(){
//
//   gl.uniform1i( webgl.modeUniformLoc, 1 );
//   var a = .1;
//   webgl.data = [
//     -1, -1, 0, a,
//     1, -1, 0, a,
//     -1,  1, 0, a,
//     -1,  1, 0, a,
//     1, -1, 0, a,
//     1,  1, 0, a
//   ];
//   webgl.draw( gl.TRIANGLES );
//   gl.uniform1i( webgl.modeUniformLoc, 0 );
//   webgl.data.length = 0;
// }
// webgl.draw = function( glType ){
//
//   gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( webgl.data ), gl.STATIC_DRAW );
//   gl.drawArrays( glType, 0, webgl.data.length / 4 );
// }
//
// var	fireworks = []
//   ,	tick = 0
//   ,	sins = []
//   ,	coss = []
//   ,	maxShardsParFirework = opts.baseShardsParFirework + opts.addedShardsParFirework
//   ,	tau = 6.283185307179586476925286766559;
//
// for( var i = 0; i < maxShardsParFirework; ++i ){
//   sins[ i ] = Math.sin( tau * i / maxShardsParFirework );
//   coss[ i ] = Math.cos( tau * i / maxShardsParFirework );
// }
//
// function Firework(){
//   this.reset();
//   this.shards = [];
//   for( var i = 0; i < maxShardsParFirework; ++i )
//     this.shards.push( new Shard( this ) );
// }
// Firework.prototype.reset = function(){
//
//   var angle = -Math.PI / 2 + ( Math.random() - .5 )* opts.fireworkAngleSpan
//     ,	vel = opts.baseFireworkVel + opts.addedFireworkVel * Math.random();
//
//   this.mode = 0;
//   this.vx = vel * Math.cos( angle );
//   this.vy = vel * Math.sin( angle );
//
//   this.x = Math.random() * w;
//   this.y = h;
//
//   this.hue = tick * opts.initHueMultiplier;
//
// }
// Firework.prototype.step = function(){
//
//   if( this.mode === 0 ){
//
//     var ph = this.hue
//       ,	px = this.x
//       ,	py = this.y;
//
//     this.hue += opts.runHueAdder;
//
//     this.x += this.vx *= opts.xFriction;
//     this.y += this.vy += opts.gravity;
//
//     webgl.data.push(
//       px, py, ph, opts.projectileAlpha * .2,
//       this.x, this.y, this.hue, opts.projectileAlpha * .2 );
//
//     if( this.vy >= opts.lowVelBoundary ){
//       this.mode = 1;
//
//       this.shardAmount = opts.baseShardsParFirework + opts.addedShardsParFirework * Math.random() | 0;
//
//       var baseAngle = Math.random() * tau
//         ,	x = Math.cos( baseAngle )
//         ,	y = Math.sin( baseAngle )
//         ,	sin = sins[ this.shardAmount ]
//         ,	cos = coss[ this.shardAmount ];
//
//       for( var i = 0; i < this.shardAmount; ++i ){
//
//         var vel = opts.baseShardVel + opts.addedShardVel * Math.random();
//         this.shards[ i ].reset( x * vel, y * vel )
//         var X = x;
//         x = x * cos - y * sin;
//         y = y * cos + X * sin;
//       }
//     }
//
//   } else if( this.mode === 1 ) {
//
//     this.ph = this.hue
//     this.hue += opts.runHueAdder;
//
//     var allDead = true;
//     for( var i = 0; i < this.shardAmount; ++i ){
//       var shard = this.shards[ i ];
//       if( !shard.dead ){
//         shard.step();
//         allDead = false;
//       }
//     }
//
//     if( allDead )
//       this.reset();
//   }
//
// }
// function Shard( parent ){
//   this.parent = parent;
// }
// Shard.prototype.reset = function( vx, vy ){
//   this.x = this.parent.x;
//   this.y = this.parent.y;
//   this.vx = this.parent.vx * opts.shardFireworkVelMultiplier + vx;
//   this.vy = this.parent.vy * opts.shardFireworkVelMultiplier + vy;
//   this.starty = this.y;
//   this.dead = false;
//   this.tick = 1;
// }
// Shard.prototype.step = function(){
//
//   this.tick += .05;
//
//   var px = this.x
//     ,	py = this.y;
//
//   this.x += this.vx *= opts.xFriction;
//   this.y += this.vy += opts.gravity;
//
//   var proportion = 1 - ( this.y - this.starty ) / ( h - this.starty );
//
//   webgl.data.push(
//     px, py, this.parent.ph, opts.projectileAlpha / this.tick,
//     this.x, this.y, this.parent.hue, opts.projectileAlpha / this.tick );
//
//   if( this.y > h )
//     this.dead = true;
// }
//
// function anim(){
//
//   window.requestAnimationFrame( anim )
//
//   webgl.clear();
//
//   ++tick;
//
//   if( fireworks.length < opts.fireworks )
//     fireworks.push( new Firework );
//
//   fireworks.map( function( firework ){ firework.step(); } );
//
//   webgl.draw( gl.LINES );
// }
// anim();
//
// window.addEventListener( 'resize', function(){
//
//   w = canvas.width = window.innerWidth;
//   h = canvas.height = window.innerHeight;
//
//   gl.viewport( 0, 0, w, h );
//   gl.uniform2f( webgl.resUniformLoc, w, h );
// })
// window.addEventListener( 'click', function( e ){
//   var firework = new Firework();
//   firework.x = e.clientX;
//   firework.y = e.clientY;
//   firework.vx = 0;
//   firework.vy = 0;
//   fireworks.push( firework );
// });




var Fireworks = function(){
  /*=============================================================================*/
  /* Utility
  /*=============================================================================*/
  var self = this;
  var rand = function(rMi, rMa){return ~~((Math.random()*(rMa-rMi+1))+rMi);}
  window.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1E3/60)}}();

  /*=============================================================================*/
  /* Initialize
  /*=============================================================================*/
  self.init = function(){
    self.dt = 0;
    self.oldTime = Date.now();
    self.canvas = document.createElement('canvas');
    self.canvasContainer = $('#canvas-container');

    var canvasContainerDisabled = document.getElementById('canvas-container');
    self.canvas.onselectstart = function() {
      return false;
    };

    self.canvas.width = self.cw = 600;
    self.canvas.height = self.ch = 400;

    self.particles = [];
    self.partCount = 30;
    self.fireworks = [];
    self.mx = self.cw/2;
    self.my = self.ch/2;
    self.currentHue = 170;
    self.partSpeed = 5;
    self.partSpeedVariance = 10;
    self.partWind = 50;
    self.partFriction = 5;
    self.partGravity = 1;
    self.hueMin = 150;
    self.hueMax = 200;
    self.fworkSpeed = 2;
    self.fworkAccel = 4;
    self.hueVariance = 30;
    self.flickerDensity = 20;
    self.showShockwave = false;
    self.showTarget = true;
    self.clearAlpha = 25;

    self.canvasContainer.append(self.canvas);
    self.ctx = self.canvas.getContext('2d');
    self.ctx.lineCap = 'round';
    self.ctx.lineJoin = 'round';
    self.lineWidth = 1;
    self.bindEvents();
    self.canvasLoop();

    self.canvas.onselectstart = function() {
      return false;
    };


  };

  /*=============================================================================*/
  /* Particle Constructor
  /*=============================================================================*/
  var Particle = function(x, y, hue){
    this.x = x;
    this.y = y;
    this.coordLast = [
      {x: x, y: y},
      {x: x, y: y},
      {x: x, y: y}
    ];
    this.angle = rand(0, 360);
    this.speed = rand(((self.partSpeed - self.partSpeedVariance) <= 0) ? 1 : self.partSpeed - self.partSpeedVariance, (self.partSpeed + self.partSpeedVariance));
    this.friction = 1 - self.partFriction/100;
    this.gravity = self.partGravity/2;
    this.hue = rand(hue-self.hueVariance, hue+self.hueVariance);
    this.brightness = rand(50, 80);
    this.alpha = rand(40,100)/100;
    this.decay = rand(10, 50)/1000;
    this.wind = (rand(0, self.partWind) - (self.partWind/2))/25;
    this.lineWidth = self.lineWidth;
  };

  Particle.prototype.update = function(index){
    var radians = this.angle * Math.PI / 180;
    var vx = Math.cos(radians) * this.speed;
    var vy = Math.sin(radians) * this.speed + this.gravity;
    this.speed *= this.friction;

    this.coordLast[2].x = this.coordLast[1].x;
    this.coordLast[2].y = this.coordLast[1].y;
    this.coordLast[1].x = this.coordLast[0].x;
    this.coordLast[1].y = this.coordLast[0].y;
    this.coordLast[0].x = this.x;
    this.coordLast[0].y = this.y;

    this.x += vx * self.dt;
    this.y += vy * self.dt;

    this.angle += this.wind;
    this.alpha -= this.decay;

    if(this.alpha < .05){
      self.particles.splice(index, 1);
    }
  };

  Particle.prototype.draw = function(){
    var coordRand = (rand(1,3)-1);
    self.ctx.beginPath();
    self.ctx.moveTo(Math.round(this.coordLast[coordRand].x), Math.round(this.coordLast[coordRand].y));
    self.ctx.lineTo(Math.round(this.x), Math.round(this.y));
    self.ctx.closePath();
    self.ctx.strokeStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+this.alpha+')';
    self.ctx.stroke();

    if(self.flickerDensity > 0){
      var inverseDensity = 50 - self.flickerDensity;
      if(rand(0, inverseDensity) === inverseDensity){
        self.ctx.beginPath();
        self.ctx.arc(Math.round(this.x), Math.round(this.y), rand(this.lineWidth,this.lineWidth+3)/2, 0, Math.PI*2, false)
        self.ctx.closePath();
        var randAlpha = rand(50,100)/100;
        self.ctx.fillStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+randAlpha+')';
        self.ctx.fill();
      }
    }
  };

  /*=============================================================================*/
  /* Create Particles
  /*=============================================================================*/
  self.createParticles = function(x,y, hue){
    var countdown = self.partCount;
    while(countdown--){
      self.particles.push(new Particle(x, y, hue));
    }
  };

  /*=============================================================================*/
  /* Update Particles
  /*=============================================================================*/
  self.updateParticles = function(){
    var i = self.particles.length;
    while(i--){
      var p = self.particles[i];
      p.update(i);
    };
  };

  /*=============================================================================*/
  /* Draw Particles
  /*=============================================================================*/
  self.drawParticles = function(){
    var i = self.particles.length;
    while(i--){
      var p = self.particles[i];
      p.draw();
    };
  };

  /*=============================================================================*/
  /* Firework Constructor
  /*=============================================================================*/
  var Firework = function(startX, startY, targetX, targetY){
    this.x = startX;
    this.y = startY;
    this.startX = startX;
    this.startY = startY;
    this.hitX = false;
    this.hitY = false;
    this.coordLast = [
      {x: startX, y: startY},
      {x: startX, y: startY},
      {x: startX, y: startY}
    ];
    this.targetX = targetX;
    this.targetY = targetY;
    this.speed = self.fworkSpeed;
    this.angle = Math.atan2(targetY - startY, targetX - startX);
    this.shockwaveAngle = Math.atan2(targetY - startY, targetX - startX)+(90*(Math.PI/180));
    this.acceleration = self.fworkAccel/100;
    this.hue = self.currentHue;
    this.brightness = rand(50, 80);
    this.alpha = rand(50,100)/100;
    this.lineWidth = self.lineWidth;
    this.targetRadius = 1;
  };

  Firework.prototype.update = function(index){
    self.ctx.lineWidth = this.lineWidth;

    vx = Math.cos(this.angle) * this.speed,
      vy = Math.sin(this.angle) * this.speed;
    this.speed *= 1 + this.acceleration;
    this.coordLast[2].x = this.coordLast[1].x;
    this.coordLast[2].y = this.coordLast[1].y;
    this.coordLast[1].x = this.coordLast[0].x;
    this.coordLast[1].y = this.coordLast[0].y;
    this.coordLast[0].x = this.x;
    this.coordLast[0].y = this.y;

    if(self.showTarget){
      if(this.targetRadius < 8){
        this.targetRadius += .25 * self.dt;
      } else {
        this.targetRadius = 1 * self.dt;
      }
    }

    if(this.startX >= this.targetX){
      if(this.x + vx <= this.targetX){
        this.x = this.targetX;
        this.hitX = true;
      } else {
        this.x += vx * self.dt;
      }
    } else {
      if(this.x + vx >= this.targetX){
        this.x = this.targetX;
        this.hitX = true;
      } else {
        this.x += vx * self.dt;
      }
    }

    if(this.startY >= this.targetY){
      if(this.y + vy <= this.targetY){
        this.y = this.targetY;
        this.hitY = true;
      } else {
        this.y += vy * self.dt;
      }
    } else {
      if(this.y + vy >= this.targetY){
        this.y = this.targetY;
        this.hitY = true;
      } else {
        this.y += vy * self.dt;
      }
    }

    if(this.hitX && this.hitY){
      var randExplosion = rand(0, 9);
      self.createParticles(this.targetX, this.targetY, this.hue);
      self.fireworks.splice(index, 1);
    }
  };

  Firework.prototype.draw = function(){
    self.ctx.lineWidth = this.lineWidth;

    var coordRand = (rand(1,3)-1);
    self.ctx.beginPath();
    self.ctx.moveTo(Math.round(this.coordLast[coordRand].x), Math.round(this.coordLast[coordRand].y));
    self.ctx.lineTo(Math.round(this.x), Math.round(this.y));
    self.ctx.closePath();
    self.ctx.strokeStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+this.alpha+')';
    self.ctx.stroke();

    if(self.showTarget){
      self.ctx.save();
      self.ctx.beginPath();
      self.ctx.arc(Math.round(this.targetX), Math.round(this.targetY), this.targetRadius, 0, Math.PI*2, false)
      self.ctx.closePath();
      self.ctx.lineWidth = 1;
      self.ctx.stroke();
      self.ctx.restore();
    }

    if(self.showShockwave){
      self.ctx.save();
      self.ctx.translate(Math.round(this.x), Math.round(this.y));
      self.ctx.rotate(this.shockwaveAngle);
      self.ctx.beginPath();
      self.ctx.arc(0, 0, 1*(this.speed/5), 0, Math.PI, true);
      self.ctx.strokeStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+rand(25, 60)/100+')';
      self.ctx.lineWidth = this.lineWidth;
      self.ctx.stroke();
      self.ctx.restore();
    }
  };

  /*=============================================================================*/
  /* Create Fireworks
  /*=============================================================================*/
  self.createFireworks = function(startX, startY, targetX, targetY){
    self.fireworks.push(new Firework(startX, startY, targetX, targetY));
  };

  /*=============================================================================*/
  /* Update Fireworks
  /*=============================================================================*/
  self.updateFireworks = function(){
    var i = self.fireworks.length;
    while(i--){
      var f = self.fireworks[i];
      f.update(i);
    };
  };

  /*=============================================================================*/
  /* Draw Fireworks
  /*=============================================================================*/
  self.drawFireworks = function(){
    var i = self.fireworks.length;
    while(i--){
      var f = self.fireworks[i];
      f.draw();
    };
  };

  /*=============================================================================*/
  /* Events
  /*=============================================================================*/
  self.bindEvents = function(){
    $(window).on('resize', function(){
      clearTimeout(self.timeout);
      self.timeout = setTimeout(function() {
        self.ctx.lineCap = 'round';
        self.ctx.lineJoin = 'round';
      }, 100);
    });

    $(self.canvas).on('mousedown', function(e){
      var randLaunch = rand(0, 5);
      self.mx = e.pageX - self.canvasContainer.offset().left;
      self.my = e.pageY - self.canvasContainer.offset().top;
      self.currentHue = rand(self.hueMin, self.hueMax);
      self.createFireworks(self.cw/2, self.ch, self.mx, self.my);

      $(self.canvas).on('mousemove.fireworks', function(e){
        var randLaunch = rand(0, 5);
        self.mx = e.pageX - self.canvasContainer.offset().left;
        self.my = e.pageY - self.canvasContainer.offset().top;
        self.currentHue = rand(self.hueMin, self.hueMax);
        self.createFireworks(self.cw/2, self.ch, self.mx, self.my);
      });

    });

    $(self.canvas).on('mouseup', function(e){
      $(self.canvas).off('mousemove.fireworks');
    });

  }

  /*=============================================================================*/
  /* Clear Canvas
  /*=============================================================================*/
  self.clear = function(){
    self.particles = [];
    self.fireworks = [];
    self.ctx.clearRect(0, 0, self.cw, self.ch);
  };

  /*=============================================================================*/
  /* Delta
  /*=============================================================================*/
  self.updateDelta = function(){
    var newTime = Date.now();
    self.dt = (newTime - self.oldTime)/16;
    self.dt = (self.dt > 5) ? 5 : self.dt;
    self.oldTime = newTime;
  }

  /*=============================================================================*/
  /* Main Loop
  /*=============================================================================*/
  self.canvasLoop = function(){
    requestAnimFrame(self.canvasLoop, self.canvas);
    self.updateDelta();
    self.ctx.globalCompositeOperation = 'destination-out';
    self.ctx.fillStyle = 'rgba(0,0,0,'+self.clearAlpha/100+')';
    self.ctx.fillRect(0,0,self.cw,self.ch);
    self.ctx.globalCompositeOperation = 'lighter';
    self.updateFireworks();
    self.updateParticles();
    self.drawFireworks();
    self.drawParticles();
  };

  self.init();

  var initialLaunchCount = 10;
  while(initialLaunchCount--){
    setTimeout(function(){
      self.fireworks.push(new Firework(self.cw/2, self.ch, rand(50, self.cw-50), rand(50, self.ch/2)-50));
    }, initialLaunchCount*200);
  }

}

/*=============================================================================*/
/* GUI
/*=============================================================================*/
var guiPresets = {
  "preset": "Default",
  "remembered": {
    "Default": {
      "0": {
        "fworkSpeed": 2,
        "fworkAccel": 4,
        "showShockwave": false,
        "showTarget": true,
        "partCount": 30,
        "partSpeed": 5,
        "partSpeedVariance": 10,
        "partWind": 50,
        "partFriction": 5,
        "partGravity": 1,
        "flickerDensity": 20,
        "hueMin": 150,
        "hueMax": 200,
        "hueVariance": 30,
        "lineWidth": 1,
        "clearAlpha": 25
      }
    },
    "Anti Gravity": {
      "0": {
        "fworkSpeed": 4,
        "fworkAccel": 10,
        "showShockwave": true,
        "showTarget": false,
        "partCount": 150,
        "partSpeed": 5,
        "partSpeedVariance": 10,
        "partWind": 10,
        "partFriction": 10,
        "partGravity": -10,
        "flickerDensity": 30,
        "hueMin": 0,
        "hueMax": 360,
        "hueVariance": 30,
        "lineWidth": 1,
        "clearAlpha": 50
      }
    },
    "Battle Field": {
      "0": {
        "fworkSpeed": 10,
        "fworkAccel": 20,
        "showShockwave": true,
        "showTarget": true,
        "partCount": 200,
        "partSpeed": 30,
        "partSpeedVariance": 5,
        "partWind": 0,
        "partFriction": 5,
        "partGravity": 0,
        "flickerDensity": 0,
        "hueMin": 20,
        "hueMax": 30,
        "hueVariance": 10,
        "lineWidth": 1,
        "clearAlpha": 40
      }
    },
    "Mega Blast": {
      "0": {
        "fworkSpeed": 3,
        "fworkAccel": 3,
        "showShockwave": true,
        "showTarget": true,
        "partCount": 500,
        "partSpeed": 50,
        "partSpeedVariance": 5,
        "partWind": 0,
        "partFriction": 0,
        "partGravity": 0,
        "flickerDensity": 0,
        "hueMin": 0,
        "hueMax": 360,
        "hueVariance": 30,
        "lineWidth": 20,
        "clearAlpha": 20
      }
    },
    "Nimble": {
      "0": {
        "fworkSpeed": 10,
        "fworkAccel": 50,
        "showShockwave": false,
        "showTarget": false,
        "partCount": 120,
        "partSpeed": 10,
        "partSpeedVariance": 10,
        "partWind": 100,
        "partFriction": 50,
        "partGravity": 0,
        "flickerDensity": 20,
        "hueMin": 0,
        "hueMax": 360,
        "hueVariance": 30,
        "lineWidth": 1,
        "clearAlpha": 80
      }
    },
    "Slow Launch": {
      "0": {
        "fworkSpeed": 2,
        "fworkAccel": 2,
        "showShockwave": false,
        "showTarget": false,
        "partCount": 200,
        "partSpeed": 10,
        "partSpeedVariance": 0,
        "partWind": 100,
        "partFriction": 0,
        "partGravity": 2,
        "flickerDensity": 50,
        "hueMin": 0,
        "hueMax": 360,
        "hueVariance": 20,
        "lineWidth": 4,
        "clearAlpha": 10
      }
    },
    "Perma Trail": {
      "0": {
        "fworkSpeed": 4,
        "fworkAccel": 10,
        "showShockwave": false,
        "showTarget": false,
        "partCount": 150,
        "partSpeed": 10,
        "partSpeedVariance": 10,
        "partWind": 100,
        "partFriction": 3,
        "partGravity": 0,
        "flickerDensity": 0,
        "hueMin": 0,
        "hueMax": 360,
        "hueVariance": 20,
        "lineWidth": 1,
        "clearAlpha": 0
      }
    }
  },
  "closed": true,
  "folders": {
    "Fireworks": {
      "preset": "Default",
      "closed": false,
      "folders": {}
    },
    "Particles": {
      "preset": "Default",
      "closed": true,
      "folders": {}
    },
    "Color": {
      "preset": "Default",
      "closed": true,
      "folders": {}
    },
    "Other": {
      "preset": "Default",
      "closed": true,
      "folders": {}
    }
  }
};


var fworks = new Fireworks();
var gui = new dat.GUI({
  autoPlace: false,
  load: guiPresets,
  preset: 'Default'
});
var customContainer = document.getElementById('gui');
customContainer.appendChild(gui.domElement);

var guiFireworks = gui.addFolder('Fireworks');
guiFireworks.add(fworks, 'fworkSpeed').min(1).max(10).step(1);
guiFireworks.add(fworks, 'fworkAccel').min(0).max(50).step(1);
guiFireworks.add(fworks, 'showShockwave');
guiFireworks.add(fworks, 'showTarget');

var guiParticles = gui.addFolder('Particles');
guiParticles.add(fworks, 'partCount').min(0).max(500).step(1);
guiParticles.add(fworks, 'partSpeed').min(1).max(100).step(1);
guiParticles.add(fworks, 'partSpeedVariance').min(0).max(50).step(1);
guiParticles.add(fworks, 'partWind').min(0).max(100).step(1);
guiParticles.add(fworks, 'partFriction').min(0).max(50).step(1);
guiParticles.add(fworks, 'partGravity').min(-20).max(20).step(1);
guiParticles.add(fworks, 'flickerDensity').min(0).max(50).step(1);

var guiColor = gui.addFolder('Color');
guiColor.add(fworks, 'hueMin').min(0).max(360).step(1);
guiColor.add(fworks, 'hueMax').min(0).max(360).step(1);
guiColor.add(fworks, 'hueVariance').min(0).max(180).step(1);

var guiOther = gui.addFolder('Other');
guiOther.add(fworks, 'lineWidth').min(1).max(20).step(1);
guiOther.add(fworks, 'clearAlpha').min(0).max(100).step(1);
guiOther.add(fworks, 'clear').name('Clear');

gui.remember(fworks);